/*
*    l3qd - Light, light, lightweight queue
*    Copyright (C) 2024  Marcus Pedersén marcus@marcux.org
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package show

import (
	"encoding/json"
	"fmt"
	"github.com/spf13/cobra"
	"notabug.org/marcux/l3q/internal/client"
	"notabug.org/marcux/l3q/internal/common"
	"os"
	"strconv"
)

var showNodeCmdFlagVerbose, showNodeCmdFlagHuman bool

var showNodeCmd = &cobra.Command{
	Use:   "node NODEID",
	Args:  cobra.ExactArgs(1),
	Short: "Shows information about specified node.",
	Long: `Description:
  Shows information about specified node.
  NODEID is required as a positional argument and is the id number of node to show.`,
	Run: func(cmd *cobra.Command, args []string) {
		nodeid, err := strconv.Atoi(args[0])

		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to parse NODEID: %s, as integer.\nNODEID is required to be a positive integer.\nTry -h or --help for help.\n",
				args[0])

			if showNodeCmdFlagVerbose {
				fmt.Fprintf(os.Stderr, "%s\n", err)
			}

			os.Exit(1)
		}

		if nodeid <= 0 {
			fmt.Fprintf(os.Stderr, "NODEID is required to be a positive integer.\nTry -h or --help for help.\n")
			os.Exit(1)
		}

		printNode(nodeid)
	},
}

func printNode(nodeid int) {
	nodes := []common.Node{}
	urlSuffix := fmt.Sprintf("/node?id=%d", nodeid)

	jsonBytes := client.UrlGet(urlSuffix, showNodeCmdFlagVerbose)
	err := json.Unmarshal(jsonBytes, &nodes)
	if err != nil {
		if showNodeCmdFlagVerbose {
			fmt.Fprintf(os.Stderr, "Failed to decode json string to struct\n%s\n.", err)
		} else {
			fmt.Fprintf(os.Stderr, "Failed to decode json string.\n")
		}
		os.Exit(1)
	}

	if len(nodes) > 1 {
		fmt.Fprintf(os.Stderr, "Wrong response from daemon.\nMore than one node in response from l3qd daemon.")
		os.Exit(1)
	} else if len(nodes) == 0 {
		os.Exit(0)
	}

	n := nodes[0]

	ram := ""
	ramUsed := ""
	swap := ""
	swapUsed := ""

	if showNodeCmdFlagHuman {
		ram = client.ScaleHuman(n.MemoryTotal)
		ramUsed = client.ScaleHuman(n.MemoryUsed)
		swap = client.ScaleHuman(n.SwapTotal)
		swapUsed = client.ScaleHuman(n.SwapUsed)
	} else {
		ram = strconv.FormatUint(n.MemoryTotal, 10)
		ramUsed = strconv.FormatUint(n.MemoryUsed, 10)
		swap = strconv.FormatUint(n.SwapTotal, 10)
		swapUsed = strconv.FormatUint(n.SwapUsed, 10)
	}

	fmt.Printf("%-20s %d\n", "Nodeid:", n.Id)
	fmt.Printf("%-20s %s\n", "Name:", n.Name)
	fmt.Printf("%-20s %s\n", "Hostname:", n.Hostname)
	fmt.Printf("%-20s %s\n", "IP address:", n.Ip)
	fmt.Printf("%-20s %d\n", "Port:", n.Port)
	fmt.Printf("%-20s %s\n", "State:", n.State)
	fmt.Printf("%-20s %d\n", "Cores total:", n.CpusTotal)
	fmt.Printf("%-20s %d\n", "Cores used:", n.CpusUsed)
	fmt.Printf("%-20s %d\n", "Cores allocated:", n.CpusAlloc)
	fmt.Printf("%-20s %s\n", "Memory total:", ram)
	fmt.Printf("%-20s %s\n", "Memory used:", ramUsed)
	fmt.Printf("%-20s %s\n", "Swap total:", swap)
	fmt.Printf("%-20s %s\n", "Swap used:", swapUsed)
}

func init() {
	showNodeCmd.Flags().BoolVarP(&showNodeCmdFlagVerbose, "verbose", "v", false, "Print verbose output")
	showNodeCmd.Flags().BoolVarP(&showNodeCmdFlagHuman, "human", "H", false, "Printing values in human readable formats")
}
